package 行为型模式

import java.math.BigDecimal
import java.math.RoundingMode


/**
 * 定义一系列的算法，把它们一个个封装起来，并且使它们可相互替换。
 * 本模式使得算法可独立于使用它的客户而变化
 */
interface DiscountStrategy {
    fun getDiscount(total: BigDecimal): BigDecimal
}

class UserDiscountStrategy : DiscountStrategy {
    override fun getDiscount(total: BigDecimal): BigDecimal {
        // 普通会员打九折:
        return total.multiply(BigDecimal("0.1")).setScale(2, RoundingMode.DOWN)
    }
}

class OverDiscountStrategy : DiscountStrategy {
    override fun getDiscount(total: BigDecimal): BigDecimal {
        // 满100减20优惠:
        return if (total >= BigDecimal.valueOf(100)) BigDecimal.valueOf(20) else BigDecimal.ZERO
    }
}

class DiscountContext {
    // 持有某个策略:
    private var strategy: DiscountStrategy = UserDiscountStrategy()

    // 允许客户端设置新策略:
    fun setStrategy(strategy: DiscountStrategy) {
        this.strategy = strategy
    }

    fun calculatePrice(total: BigDecimal): BigDecimal {
        return total.subtract(strategy.getDiscount(total)).setScale(2)
    }
}

// 策略接口
interface PaymentStrategy {
    fun calculateAmount(amount: Double): Double
}

// 具体策略类：支付宝支付
class AlipayStrategy : PaymentStrategy {
    override fun calculateAmount(amount: Double): Double {
        return amount * 0.9 // 享受 9 折优惠
    }
}

// 具体策略类：微信支付
class WechatPayStrategy : PaymentStrategy {
    override fun calculateAmount(amount: Double): Double {
        return amount * 0.95 // 享受 95 折优惠
    }
}

// 具体策略类：银行卡支付
class CardPayStrategy : PaymentStrategy {
    override fun calculateAmount(amount: Double): Double {
        return amount // 不享受任何优惠
    }
}

// 上下文类：商品订单
class Order(private val paymentStrategy: PaymentStrategy) {
    fun calculateTotalAmount(amount: Double): Double {
        return paymentStrategy.calculateAmount(amount)
    }
}

// 客户端代码
fun main() {
    val amount = 100.0
    val alipayStrategy = AlipayStrategy()
    val wechatPayStrategy = WechatPayStrategy()
    val cardPayStrategy = CardPayStrategy()

    val order1 = Order(alipayStrategy)
    println("支付宝支付金额：${order1.calculateTotalAmount(amount)}")

    val order2 = Order(wechatPayStrategy)
    println("微信支付金额：${order2.calculateTotalAmount(amount)}")

    val order3 = Order(cardPayStrategy)
    println("银行卡支付金额：${order3.calculateTotalAmount(amount)}")
}